
#include"vcylinder.h"
#include<stdlib.h>
#include<math.h>
#include<stdio.h>
#include"algebra.h"

void VCylinder::FillCoordAndBox ()
{
  printf("VCylinder %d %d\n", n_vertices,n_triangles);
  float * vertices = GetVertArray();
  float theta_step = 2*_PI/(n-1);
  float h_step = 1.0/(n-1.0);
  float radius = 1*m_ratio;
  int v_id=0;
  for(int u=0;u<n;u++){
    for(int v=0;v<n;v++){
      float theta = v*theta_step;
      vertices[v_id*3] = radius*cos(theta);
      vertices[v_id*3+1] = u*h_step;
      vertices[v_id*3+2] = radius*sin(theta);
      //printf("x=%f y=%f z=%f\n",vertices[v_id*3],vertices[v_id*3+1],vertices[v_id*3+2]);
      v_id++;
    }
  }
  CalcNormals();
  xmax= 1.0;
  ymax= 1.0;
  zmax= 1.0;
  xmin=-1.0;
  //ymin=-1.0;
  ymin= 0.0;
  zmin=-1.0;
}

void VCylinder::ShapeCurve (float * c)
{
  int v_id=0;
  float * vertices = GetVertArray();
  Matrix Rot;
  for(int u=0;u<n;u++){
    int id1 = u!=n-1?u*3:(u-1)*3;
    int id2 = u!=n-1?(u+1)*3:u*3;
    Vector vcurv = algVector(c[id2]-c[id1],c[id2+1]-c[id1+1],c[id2+2]-c[id2+2],1);
    vcurv = algUnit(vcurv);
    Vector vcenter = algVector(0.0,1.0,0.0,1.0);
    Vector vaxis = algCross(vcurv,vcenter);
    float dot = algDot(vcurv,vcenter);
    float theta = acos(dot);
    //pega a matriz de rotacao
    Rot = algMatrixRotate(-theta*180.0/_PI, vaxis.x, vaxis.y, vaxis.z);
    //Matriz T deve Trazer o vetor para y = 0, rotacionar e transladar para a 
    //posicao da curva
    Matrix T = algMult(algMatrixTransl(c[id1],c[id1+1],c[id1+2]),Rot);
    T = algMult(T,algMatrixTransl(0.0,-vertices[v_id*3+1],0.0));
    for(int v=0;v<n;v++){
      Vector temp = algVector(vertices[v_id*3],vertices[v_id*3+1],vertices[v_id*3+2],1.0);
      temp = algTransf(T, temp);
      vertices[v_id*3]   = temp.x;
      vertices[v_id*3+1] = temp.y;
      vertices[v_id*3+2] = temp.z;
      
      xmax = xmax>vertices[v_id*3]?xmax:vertices[v_id*3];
      xmin = xmin<vertices[v_id*3]?xmin:vertices[v_id*3];
      ymax = ymax>vertices[v_id*3+1]?ymax:vertices[v_id*3+1];
      ymin = ymin<vertices[v_id*3+1]?ymin:vertices[v_id*3+1];
      zmax = zmax>vertices[v_id*3+2]?zmax:vertices[v_id*3+2];
      zmin = zmin<vertices[v_id*3+2]?zmin:vertices[v_id*3+2];

      v_id++;
    }
  }
  CalcNormals();
}

void VCylinder::SinShape ()
{
  float * curv = (float*)malloc(sizeof(float)*n*3);
  //float theta_step = 6*_PI/(n-1);
  float theta_step = 2*_PI/(n-1);
  float h_step = 1.0/(n-1.0);
  for(int t=0;t<n;t++){
    int id =t*3;
    curv[id] = sin(theta_step*t)*0.1;
    curv[id+1] = h_step*t;
    curv[id+2] = 0.0;
  }
  ShapeCurve(curv);
  free(curv);
  //InvertNormals();
}

//    x = (2+\cos 3t)\cos 2t, \qquad y=(2+\cos 3t )\sin 2t, \qquad z=\sin 3t. 
void VCylinder::KnotShape ()
{
  float * curv = (float*)malloc(sizeof(float)*n*3);
  float t_step = 6.35/(n-1.0);
  for(int i=0;i<n;i++){
    int id = i*3;
    float t = i*t_step;
    curv[id] = (2+cos(3*t))*cos(2*t);
    curv[id+2] = (2+cos(3*t))*sin(2*t);
    curv[id+1] = sin(3*t);
  }
  ShapeCurve(curv);
  free(curv);
}


